package game;

import static org.lwjgl.opengl.GL11.GL_LINES;
import static org.lwjgl.opengl.GL11.GL_QUADS;
import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glColor3f;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.glLineWidth;
import static org.lwjgl.opengl.GL11.glVertex2i;
import game.graphics.Block;
import helpers.Text;

import java.io.Serializable;
import java.util.Enumeration;
import java.util.Hashtable;

import org.newdawn.slick.Color;

import data.DataManager;
import data.DataManager.BlockType;

/**
 * Implements inventory which is used in game.
 * It's used for storing removed blocks.
 * 
 * @author Tomas Zima
 */
public class Inventory implements Serializable
{
	/**
	 * Returns instance of inventory
	 * (this class is a singleton).
	 * 
	 * @return
	 */
	public static Inventory getInstance()
	{
		if (instance == null)
		{
			instance = new Inventory();
		}
		
		return instance;
	}
	
	/**
	 * Constructor.
	 */
	private Inventory()
	{
		//
	}
	
	/**
	 * Redraws inventory.
	 */
	public void redraw()
	{
		// Draws background
		glColor3f(0.3f, 0.0f, 0.0f);
		glBegin(GL_QUADS);
			glVertex2i(posLeftUpCornerX, posLeftUpCornerY);
			glVertex2i(posLeftUpCornerX + WIDTH, posLeftUpCornerY);
			glVertex2i(posLeftUpCornerX + WIDTH, posLeftUpCornerY + HEIGHT);
			glVertex2i(posLeftUpCornerX, posLeftUpCornerY + HEIGHT);
		glEnd();
		
		// Draws rectangles which represents places for items
		glLineWidth(2.0f);
		glColor3f(0.3f, 0.3f, 0.3f);
		glBegin(GL_LINES);
			glVertex2i(posLeftUpCornerX, posLeftUpCornerY);
			glVertex2i(posLeftUpCornerX + WIDTH, posLeftUpCornerY);
			
			glVertex2i(posLeftUpCornerX, posLeftUpCornerY + HEIGHT);
			glVertex2i(posLeftUpCornerX + WIDTH, posLeftUpCornerY + HEIGHT);
		
			for (int i = posLeftUpCornerX; i < posLeftUpCornerX + WIDTH; i += 50)
			{
				glVertex2i(i, posLeftUpCornerY);
				glVertex2i(i, posLeftUpCornerY + HEIGHT);
			}
			
		glEnd();

		// Used for iterating
		Enumeration<BlockType> e = blockItems.keys();

		// Draws all blocks and its count
		for (int i = 74; i < 1024 - 200; i += 50)
		{
			if (e.hasMoreElements())
			{
				BlockType t = (BlockType) e.nextElement();
				
				new Block(t).redraw(i + 9, 9);
				new Text(i + 9, 9, Integer.toString(blockItems.get(t)), new Color(1.0f, 1.0f, 1.0f)).redraw();
			}
		}
		
		// Draws borders for active item
		glLineWidth(5.0f);
		glColor3f(0.8f, 0.8f, 0.8f);
		glBegin(GL_LINES);
			// up
			glVertex2i(posLeftUpCornerX + (selectedItemIndex - 1) * FIELD_SIZE, posLeftUpCornerY);
			glVertex2i(posLeftUpCornerX + FIELD_SIZE * selectedItemIndex, posLeftUpCornerY);
			
			// down
			glVertex2i(posLeftUpCornerX + FIELD_SIZE * selectedItemIndex, posLeftUpCornerY + HEIGHT);
			glVertex2i(posLeftUpCornerX + (selectedItemIndex - 1) * FIELD_SIZE, posLeftUpCornerY + HEIGHT);
			
			// left
			glVertex2i(posLeftUpCornerX + (selectedItemIndex - 1) * FIELD_SIZE, posLeftUpCornerY);
			glVertex2i(posLeftUpCornerX + (selectedItemIndex - 1) * FIELD_SIZE, posLeftUpCornerY + FIELD_SIZE);
			
			// right
			glVertex2i(posLeftUpCornerX + FIELD_SIZE * selectedItemIndex, posLeftUpCornerY);
			glVertex2i(posLeftUpCornerX + FIELD_SIZE * selectedItemIndex, posLeftUpCornerY + HEIGHT);
		glEnd();
	}
	
	/**
	 * Adds item into inventory.
	 * If player don't have any, it will be created. In other case,
	 * count of this items will be increased by one.
	 * 
	 * @param blockType
	 */
	public void addItem(DataManager.BlockType blockType)
	{
		// There isn't any item of this sort
		if (blockItems.get(blockType) == null)
		{
			blockItems.put(blockType, 1);
		}
		// There are some items of this sort by the time
		else
		{
			blockItems.put(blockType, blockItems.get(blockType) + 1);
		}
	}
	
	/**
	 * Add specified count of items into the inventory.
	 * 
	 * @param blockType
	 * @param count
	 */
	public void addItems(DataManager.BlockType blockType, int count)
	{
		// There isn't any item of this sort
		if (blockItems.get(blockType) == null)
		{
			blockItems.put(blockType, count);
		}
		// There are some items of this sort currently
		else
		{
			// Count of items must be a positive number greater than zero,
			// because in other case it would be possible to decrease count
			// of items instead of increasing it.
			if (count > 0)
			{
				blockItems.put(blockType, blockItems.get(blockType) + count);
			}
		}
	}
	
	/**
	 * Remove one item.
	 * 
	 * @param blockType
	 */
	public void removeItem(DataManager.BlockType blockType)
	{
		// Only if there are some items of this sort
		if (blockItems.get(blockType) != null)
		{
			blockItems.put(blockType, blockItems.get(blockType) - 1);
		}
	}
	
	/**
	 * Remove specified count of items.
	 * 
	 * @param blockType
	 * @param count
	 */
	public void removeItems(DataManager.BlockType blockType, int count)
	{
		// Only if there are some items of this sort
		if (blockItems.get(blockType) != null)
		{
			// Count of removed items must be equal or greater than one,
			// because in the other case, it would be possible to add items
			// by negative number.
			if (count >= 1)
			{
				// Remove items
				blockItems.put(blockType, blockItems.get(blockType) - count);
				
				// If count of items is under zero now, remove this sort of object
				// from invetory
				if (blockItems.get(blockType) <= 0)
				{
					blockItems.remove(blockType);
				}
			}
		}
	}
	
	/**
	 * Returns type of item which is currently selected.
	 * 
	 * @return
	 */
	public BlockType getSelectedItem()
	{
		return (BlockType) blockItems.keySet().toArray()[selectedItemIndex];
	}
	
	/**
	 * Move cursor for selecting items to the right.
	 */
	public void itemSelectRight()
	{
		// Increase cursor by one
		selectedItemIndex++;
		
		// If it's in the end, set it back to the begin
		if (selectedItemIndex > 15)
		{
			selectedItemIndex = 1;
		}
	}
	
	private static Inventory instance;
	private Hashtable<DataManager.BlockType, Integer> blockItems = new Hashtable<DataManager.BlockType, Integer>();
	private int selectedItemIndex = 1;
	
	private int posLeftUpCornerX = 74;
	private int posLeftUpCornerY = 0;
	
	private final int WIDTH = 750;
	private final int HEIGHT = 50;
	
	private final int FIELD_SIZE = 50;
}
